#include "NamespaceBuilder.h"

#include "ScriptCompiler/AST/NamespaceNode.h"

#include "ScriptCompiler/ASTBuilder/NamespaceContentBuilder.h"
#include "ScriptCompiler/ScriptFileContext.h"

CNamespaceBuilder::CNamespaceBuilder(std::shared_ptr<CScriptFileContext> InContext,bool InIsGlobal)
{
    Context = InContext;
    Result = std::make_shared<CNamespaceNode>(InContext);

    State = EState::WatingNamespacekeyword;
}

bool CNamespaceBuilder::ReadCurentToken()
{
    auto Token = Context->GetCurrentToken();

    switch(State)
    {
        case EState::WatingNamespacekeyword:
        {
            if(Token->Type != EScriptTokenType::Namespace)
            {
                Context->RaiseError(10068,Token, U"Expecting namespace keyword");
                return false;
            }
            Result->Namespace = Token;
            State = EState::WatingNamespaceName;
            Context->CurrentTokenIndex++;
            return ReadCurentToken();
        }

        case EState::WatingNamespaceName:
        {
            if(Token->Type != EScriptTokenType::Identifier)
            {
                Context->RaiseError(10069,Token, U"Expecting namespace name");
                return false;
            }
            Result->NameChain.Add(Token);
            Context->CurrentTokenIndex++;
 
            auto NextToken=Context->GetCurrentToken();
            if(NextToken->Type == EScriptTokenType::Dot)
            {
                //skip dot
                Context->CurrentTokenIndex++;

                return ReadCurentToken();
            }

            State = EState::WatingLeftBrace;
            return ReadCurentToken();
        }

        case EState::WatingLeftBrace:
        {
            if(Token->Type != EScriptTokenType::LeftBrace)
            {
                Context->RaiseError(10070,Token, U"Expecting {");
                return false;
            }
            State = EState::WatingRightBrace;
            Context->CurrentTokenIndex++;
            return ReadCurentToken();
        }

        case EState::WatingRightBrace:
        {
            //build namespace content
            auto NewNamespaceContentBuilder = std::make_shared<CNamespaceContentBuilder>(Context,Result);
            if(!NewNamespaceContentBuilder->ReadCurentToken())
            {
                return false;
            }

            Token=Context->GetCurrentToken();
            if(Token->Type!=EScriptTokenType::RightBrace)
            {
                Context->RaiseError(10072,Token, U"Expecting } at end of namespace");
                return false;
            }
            //skip right brace
            Context->CurrentTokenIndex++;
            return true;
        }
    }



}
